/// \file owl_handler.cpp.
///============================================================================\n
/// Name        : owl_handler.cpp\n
/// Author      : Gergely Lukacsy (info@dlog-reasoner.org)\n
/// Version     : 0.01\n
/// Copyright   : DERI\n
/// Description : Specialisation for Xerces DefaultHandler for OWL processing,\n
///               implementation file.\n
/// 
/// This file is part of the DParser and DLog 2 projects.\n
///============================================================================

// constructor
OWLCALLBACK::OWLCALLBACK(const XMLCh* pElement, HOOKFUNCTION pHook) {
	init(pElement, pHook);
}

OWLCALLBACK::OWLCALLBACK(const XMLCh* pElement, HOOKFUNCTION pHook, PARAMETERS& params) {
	mParameters = params;
	init(pElement, pHook);
}

void OWLCALLBACK::init(const XMLCh* pElement, HOOKFUNCTION pHook) {
	pElementName = pElement;
	pHookFunction = pHook;
}

// This number is generated to achieve perfect hashing.
DWORD OWLHANDLER::nrBuckets = 495;

// For perfect hash generating
// bool bPerfectHash;
// SET<unsigned long> hBuckets;

// constructor
OWLHANDLER::OWLHANDLER():
	pOWLParser(NULL),
	bPropertyCharacteristicModeOn(false),
	mPropertyCharacteristic(0),
	bLiteralModeOn(false),
	pSavedHookStructure(NULL),
	pBasePrefix(NULL) {

	pAttrCharsToRelease[0] = NULL;
	pAttrCharsToRelease[1] = NULL;


//  label1:

	// initialize the perfect hash table
	callbacks = new OWLCALLBACK*[nrBuckets];

//  	DBG("Trying with nrBucket %d", nrBuckets);
//  	bPerfectHash = true;

	for (unsigned int i = 0; i < nrBuckets; ++i) {
		callbacks[i] = NULL;
	}

	//
	// build the perfect hash table storing element-callback assignments
	//

	// axioms
	register_callback(new OWLCALLBACK(XMLEquivalentClasses, &OWLHANDLER::pushOWLSAXAxiomToStack<EQUIVALENTCONCEPTS>));
	register_callback(new OWLCALLBACK(XMLDatatypeDefinition, &OWLHANDLER::pushOWLSAXAxiomToStack<EQUIVALENTCONCEPTS>));
	register_callback(new OWLCALLBACK(XMLSubClassOf, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBCONCEPT>));

	register_callback(new OWLCALLBACK(XMLSubObjectPropertyOf, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBROLE>));
	register_callback(new OWLCALLBACK(XMLSubDataPropertyOf, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBROLE>));

	// XMLPropertyChain does not have a callback deliberately

	register_callback(new OWLCALLBACK(XMLEquivalentObjectProperties, &OWLHANDLER::pushOWLSAXAxiomToStack<EQUIVALENTROLES>));
	register_callback(new OWLCALLBACK(XMLEquivalentDataProperties, &OWLHANDLER::pushOWLSAXAxiomToStack<EQUIVALENTROLES>));

	register_callback(new OWLCALLBACK(XMLDisjointClasses, &OWLHANDLER::pushOWLSAXAxiomToStack<DISJOINTCONCEPTS>));
	register_callback(new OWLCALLBACK(XMLDisjointObjectProperties, &OWLHANDLER::pushOWLSAXAxiomToStack<DISJOINTROLES>));
	register_callback(new OWLCALLBACK(XMLDisjointDataProperties, &OWLHANDLER::pushOWLSAXAxiomToStack<DISJOINTROLES>));

	PARAMETERS paramDomain;
	PARAMETERS paramRange;
	paramDomain.insert(PARAMPAIR(parSUBCONCEPTORIGIN, valDOMAIN));
	paramRange.insert(PARAMPAIR(parSUBCONCEPTORIGIN, valRANGE));
	register_callback(new OWLCALLBACK(XMLObjectPropertyDomain, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBCONCEPT>, paramDomain));
	register_callback(new OWLCALLBACK(XMLDataPropertyDomain, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBCONCEPT>, paramDomain));
	register_callback(new OWLCALLBACK(XMLObjectPropertyRange, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBCONCEPT>, paramRange));
	register_callback(new OWLCALLBACK(XMLDataPropertyRange, &OWLHANDLER::pushOWLSAXAxiomToStack<SUBCONCEPT>, paramRange));


	PARAMETERS paramInverses;
	paramInverses.insert(PARAMPAIR(parEQUIVALENTROLEORIGIN, valINVERSES));
	register_callback(new OWLCALLBACK(XMLInverseObjectProperties, &OWLHANDLER::pushOWLSAXAxiomToStack<EQUIVALENTROLES>, paramInverses));

	PARAMETERS paramDisjointUnion;
	paramDisjointUnion.insert(PARAMPAIR(parEQUIVALENTCONCEPTORIGIN, valDISJOINTUNION));
	register_callback(new OWLCALLBACK(XMLDisjointUnion, &OWLHANDLER::pushOWLSAXAxiomToStack<EQUIVALENTCONCEPTS>, paramDisjointUnion));


	// role characteristics
	// A property characteristic axiom is stated either on an atomic role or on an inverse.
	// The idea is that we do not have to take care of the inverses as if a relation is
	// reflexive, irreflexive, symmetric, asymmetric, transitive then the inverse is also.
	//
	// The only exceptions are functional and inverse functional properties.
	// Here we count the number of inverses and "invert" the characteristic accordingly.

	register_callback(new OWLCALLBACK(XMLFunctionalObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bFUNCTIONAL>));
	register_callback(new OWLCALLBACK(XMLFunctionalDataProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bFUNCTIONAL>));
	register_callback(new OWLCALLBACK(XMLInverseFunctionalObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bINVERSEFUNCTIONAL>));
	register_callback(new OWLCALLBACK(XMLReflexiveObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bREFLEXIVE>));
	register_callback(new OWLCALLBACK(XMLIrreflexiveObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bIRREFLEXIVE>));
	register_callback(new OWLCALLBACK(XMLSymmetricObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bSYMMETRIC>));
	register_callback(new OWLCALLBACK(XMLAsymmetricObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bASYMMETRIC>));
	register_callback(new OWLCALLBACK(XMLTransitiveObjectProperty, &OWLHANDLER::enterIntoOWLCharacteristicsMode<bTRANSITIVE>));

	// Concept constructors
	register_callback(new OWLCALLBACK(XMLClass, &OWLHANDLER::pushAtomicConcept));
	register_callback(new OWLCALLBACK(XMLObjectComplementOf, &OWLHANDLER::pushOWLSAXElementToStack<NEGATED>));
	register_callback(new OWLCALLBACK(XMLObjectSomeValuesFrom, &OWLHANDLER::pushOWLSAXElementToStack<EXISTS>));
	register_callback(new OWLCALLBACK(XMLObjectAllValuesFrom, &OWLHANDLER::pushOWLSAXElementToStack<FORALL>));
	register_callback(new OWLCALLBACK(XMLObjectIntersectionOf, &OWLHANDLER::pushOWLSAXElementToStack<INTERSECTION>));
	register_callback(new OWLCALLBACK(XMLObjectUnionOf, &OWLHANDLER::pushOWLSAXElementToStack<UNION>));
	PARAMETERS paramMinCardinality;
	PARAMETERS paramMaxCardinality;
	PARAMETERS paramExactCardinality;
	paramMinCardinality.insert(PARAMPAIR(parCARDINALITYTYPE, valMINCARDINALITY));
	paramMaxCardinality.insert(PARAMPAIR(parCARDINALITYTYPE, valMAXCARDINALITY));
	paramExactCardinality.insert(PARAMPAIR(parCARDINALITYTYPE, valEXACTCARDINALITY));
	register_callback(new OWLCALLBACK(XMLObjectMinCardinality, &OWLHANDLER::pushOWLSAXElementToStack<CARDINALITY>, paramMinCardinality));
	register_callback(new OWLCALLBACK(XMLObjectMaxCardinality, &OWLHANDLER::pushOWLSAXElementToStack<CARDINALITY>, paramMaxCardinality));
	register_callback(new OWLCALLBACK(XMLObjectExactCardinality, &OWLHANDLER::pushOWLSAXElementToStack<CARDINALITY>, paramExactCardinality));

	register_callback(new OWLCALLBACK(XMLDataMinCardinality, &OWLHANDLER::pushOWLSAXElementToStack<CARDINALITY>, paramMinCardinality));
	register_callback(new OWLCALLBACK(XMLDataMaxCardinality, &OWLHANDLER::pushOWLSAXElementToStack<CARDINALITY>, paramMaxCardinality));
	register_callback(new OWLCALLBACK(XMLDataExactCardinality, &OWLHANDLER::pushOWLSAXElementToStack<CARDINALITY>, paramExactCardinality));


	PARAMETERS paramDataType;
	paramDataType.insert(PARAMPAIR(parABSTRACTTYPE, valCONCRETE));
	register_callback(new OWLCALLBACK(XMLDatatype, &OWLHANDLER::pushAtomicConcept, paramDataType));
	register_callback(new OWLCALLBACK(XMLDataIntersectionOf, &OWLHANDLER::pushOWLSAXElementToStack<INTERSECTION>));
	register_callback(new OWLCALLBACK(XMLDataUnionOf, &OWLHANDLER::pushOWLSAXElementToStack<UNION>));
	register_callback(new OWLCALLBACK(XMLDataComplementOf, &OWLHANDLER::pushOWLSAXElementToStack<NEGATED>));

	register_callback(new OWLCALLBACK(XMLDataSomeValuesFrom, &OWLHANDLER::pushOWLSAXElementToStack<EXISTS>));
	register_callback(new OWLCALLBACK(XMLDataAllValuesFrom, &OWLHANDLER::pushOWLSAXElementToStack<FORALL>));

	register_callback(new OWLCALLBACK(XMLObjectHasSelf, &OWLHANDLER::pushOWLSAXElementToStack<HASSELF>));
	register_callback(new OWLCALLBACK(XMLObjectHasValue, &OWLHANDLER::pushOWLSAXElementToStack<EXISTS>));
	register_callback(new OWLCALLBACK(XMLDataHasValue, &OWLHANDLER::pushOWLSAXElementToStack<EXISTS>));
	register_callback(new OWLCALLBACK(XMLObjectOneOf, &OWLHANDLER::pushOWLSAXElementToStack<UNION>));
	register_callback(new OWLCALLBACK(XMLDataOneOf, &OWLHANDLER::pushOWLSAXElementToStack<UNION>));


	// Property constructors
	register_callback(new OWLCALLBACK(XMLObjectProperty, &OWLHANDLER::pushAtomicRole));
	register_callback(new OWLCALLBACK(XMLInverseObjectProperty, &OWLHANDLER::pushInverse));

	// concrete role expressions
	PARAMETERS paramDataProperty;
	paramDataProperty.insert(PARAMPAIR(parPROPERTYTYPE, valDATAPROPERTY));
	register_callback(new OWLCALLBACK(XMLDataProperty, &OWLHANDLER::pushAtomicRole, paramDataProperty));

	// Instances
	PARAMETERS paramNegative;
	PARAMETERS paramLiteral;
	paramNegative.insert(PARAMPAIR(parASSERTIONTYPE, valNEGATIVE));
	paramLiteral.insert(PARAMPAIR(parINSTANCETYPE, valLITERAL));
	register_callback(new OWLCALLBACK(XMLNamedIndividual, &OWLHANDLER::pushInstance));
	register_callback(new OWLCALLBACK(XMLAnonymousIndividual, &OWLHANDLER::pushInstance));
	register_callback(new OWLCALLBACK(XMLLiteral, &OWLHANDLER::pushInstance, paramLiteral));

	register_callback(new OWLCALLBACK(XMLClassAssertion, &OWLHANDLER::pushOWLSAXAxiomToStack<CINSTANCE>));
	register_callback(new OWLCALLBACK(XMLSameIndividual, &OWLHANDLER::pushOWLSAXAxiomToStack<SAMEINSTANCES>));
	register_callback(new OWLCALLBACK(XMLDifferentIndividuals, &OWLHANDLER::pushOWLSAXAxiomToStack<DIFFERENTINSTANCES>));

	register_callback(new OWLCALLBACK(XMLObjectPropertyAssertion, &OWLHANDLER::pushOWLSAXAxiomToStack<RINSTANCE>));
	register_callback(new OWLCALLBACK(XMLDataPropertyAssertion, &OWLHANDLER::pushOWLSAXAxiomToStack<RINSTANCE>));
	register_callback(new OWLCALLBACK(XMLNegativeObjectPropertyAssertion, &OWLHANDLER::pushOWLSAXAxiomToStack<RINSTANCE>, paramNegative));
	register_callback(new OWLCALLBACK(XMLNegativeDataPropertyAssertion, &OWLHANDLER::pushOWLSAXAxiomToStack<RINSTANCE>, paramNegative));

	// Keys
	register_callback(new OWLCALLBACK(XMLHasKey, &OWLHANDLER::pushOWLSAXAxiomToStack<HASKEY>));

	// prefixes
	register_callback(new OWLCALLBACK(XMLPrefix, &OWLHANDLER::extendPrefixTable));
	register_callback(new OWLCALLBACK(XMLOntology, &OWLHANDLER::extendPrefixTable));


	// facets
	register_callback(new OWLCALLBACK(XMLDatatypeRestriction, &OWLHANDLER::pushOWLSAXElementToStack<RESTRICTION>));
	register_callback(new OWLCALLBACK(XMLFacetRestriction, &OWLHANDLER::pushOWLSAXElementToStack<FACET>));

	register_callback(new OWLCALLBACK(XMLImport, &OWLHANDLER::doNothing));
	register_callback(new OWLCALLBACK(XMLDeclaration, &OWLHANDLER::doNothing));


// 	if (!bPerfectHash) {
// 
// 		// delete the entries of the hash table
// 		for (unsigned int i = 0; i < nrBuckets; ++i) {
// 			delete callbacks[i];
// 		}
// 
// 		// delete hash table
// 		delete [] callbacks;
// 
// 		hBuckets.clear();
// 
// 		nrBuckets++;
// 		ASSERT(nrBuckets < 30000);
// 
// 		goto label1;
// 	} else {
// 		DBG("Size of the perfect hash table is %d", nrBuckets);
// 	}
}


unsigned long OWLHANDLER::__hash_xerces_name(const XMLCh* __s) {
	unsigned long __h = 0;
	for ( ; *__s; ++__s) {
		__h = 5*__h + *__s;
	}

	__h = __h % nrBuckets;

// 	//We use this to generate a perfect hash function.
// 	PAIR<SET<unsigned long>::iterator, bool> res = hBuckets.insert(__h);
// 	if (res.second == false)
// 		bPerfectHash =false;

	return __h;
}

void OWLHANDLER::register_callback(OWLCALLBACK* pCallBack) {
	// calculate which bucket this callback should go
	unsigned long __h = __hash_xerces_name(pCallBack->pElementName);

	// check if the bucket already contains something
	ASSERT(callbacks[__h] == NULL);

	// register callback
	callbacks[__h] = pCallBack;
}

OWLCALLBACK* OWLHANDLER::obtain_callback(const XMLCh* pName) {
	// calculate which bucket this callback should be
	unsigned long __h = __hash_xerces_name(pName);

	// check if the bucket is empty and return if so
	if (callbacks[__h] == NULL)
		return NULL;

	// otherwise we have to double-check (unfortunately) that we indeed found the one we were looking for
	if (XMLString::equals(callbacks[__h]->pElementName, pName)) 
		return callbacks[__h];
	else
		return NULL;

}

void OWLHANDLER::init() {
	// set up dummy objects, cannot be done at constructor time
	PARAMETERS v;
	pDummyAtomicConcept = new (pOWLParser->pKnowledgeBase->mPool) ATOMICCONCEPT(v);
	pDummyAtomicRole = new (pOWLParser->pKnowledgeBase->mPool) ATOMICROLE(v);
	pDummyInstance = new (pOWLParser->pKnowledgeBase->mPool) INSTANCE(v);
}

// Destructor.
OWLHANDLER::~OWLHANDLER() {

	// delete the entries of the hash table
	for (unsigned int i = 0; i < nrBuckets; ++i) {
		delete callbacks[i];
	}

	// delete hash table
	delete [] callbacks;
}

// binary search
// OWLCALLBACK* OWLHANDLER::binaryHookSearch(OWLCALLBACKVECTOR& v, const XMLCh* pElement) {
// 	 unsigned nLow = 0;
// 	 unsigned nHigh = v.size();
// 
// 	 while (nLow < nHigh) {
// 		INT nMid = nLow + ((nHigh - nLow) / 2);
// 
// 	    if (XMLString::compareString(v[nMid]->pElementName,pElement) < 0)
// 	    	nLow = nMid + 1;
// 		else
// 			nHigh = nMid;
// 	 }
// 
// 	 if ((nLow < v.size()) && (XMLString::equals(v[nLow]->pElementName,pElement)))
// 	           return v[nLow];
// 	       else
// 	           return NULL;
// }

void OWLHANDLER::doNothing(PARAMETERS& params) {
}

template<unsigned char FLAG>
void OWLHANDLER::enterIntoOWLCharacteristicsMode(PARAMETERS& params) {
	// assert that we are about to enter into this special mode
	ASSERT(!bPropertyCharacteristicModeOn);
	ASSERT(mPropertyCharacteristic == 0);
	ASSERT(pOWLParser->mStack.empty());

	// set mode active
	bPropertyCharacteristicModeOn = true;

	// remember the flag
	mPropertyCharacteristic = FLAG;
}

/// Member function template for compact representation of the processing of normal OWL elements.
template<typename T>
void OWLHANDLER::pushOWLSAXElementToStack(PARAMETERS& params) {
	// Normal elements cannot be on top level;
	if (pOWLParser->mStack.empty()) return;

	// push to stack
	_pushToStack<T>(params);
}

/// Member function template for compact representation of the processing of normal OWL axioms.
template<typename T>
void OWLHANDLER::pushOWLSAXAxiomToStack(PARAMETERS& params) {
	// Axioms must be on top level
	ASSERT(pOWLParser->mStack.empty());

	// push to stack
	_pushToStack<T>(params);
}

template<typename T>
void OWLHANDLER::_pushToStack(PARAMETERS& params) {
	// create new instance by using the block allocator of the Knowledge Base.
	T* pNewObject = new (pOWLParser->pKnowledgeBase->mPool) T(params);

	// push the new instance to the stack
	pOWLParser->mStack.push(pNewObject);
}

//
// Special cases
//
template <typename T>
void OWLHANDLER::_pushAtomic(PARAMETERS& params, T*& pDummyAtomic) {
	// obtain identifier of the atomic construct
	PARAMETERSITERATOR iter = params.find(parPREFIX);
	ASSERT(iter != params.end());
	const char* pPrefix = iter->second.pString;

	iter = params.find(parIRI);
	ASSERT(iter != params.end());
	const char* pName = iter->second.pString;

	// configure our dummy object
	pDummyAtomic->setURIUnsafe(pPrefix, pName);

	// try to insert this object to the cache
	T* pInsertedAtomic = pOWLParser->pKnowledgeBase->addAtomic(pDummyAtomic);

	// check if we actually managed to insert
	// if the object was already in the cache we are simply happy
	if (pInsertedAtomic == pDummyAtomic) {

		// copy the URI to make it persistent
		// we use here also the blockallocator
		char* pNewURI = new (pOWLParser->pKnowledgeBase->mPool) char[strlen(pName) + 1];
		strcpy(pNewURI, pName);

		// this is safe now
		pInsertedAtomic->setURIUnsafe(pPrefix, pNewURI);

		// instantiate a new dummy atomic concept/role
		PARAMETERS ps;
		pDummyAtomic = new (pOWLParser->pKnowledgeBase->mPool) T(ps);
	}

	// push object to stack
	pOWLParser->mStack.push(pInsertedAtomic);
}


void OWLHANDLER::pushInstance(PARAMETERS& params) {
	// Instances cannot be on top level.
	if (pOWLParser->mStack.empty()) return;

	// check if this instance is actually a literal...
	PARAMETERSITERATOR iter = params.find(parINSTANCETYPE);
	if ((iter != params.end()) && (static_cast<INSTANCETYPES>(iter->second.nValue) == valLITERAL)) {
		pDummyInstance->extendProperty(bLITERAL);
	}

	// push object in a cache aware way
	_pushAtomic<INSTANCE>(params, pDummyInstance);
}


void OWLHANDLER::pushAtomicConcept(PARAMETERS& params) {
	// Atomic concepts cannot be on top level.
	if (pOWLParser->mStack.empty()) return;

	// set datatype bit is this is indeed a concrete concept
	PARAMETERSITERATOR iter = params.find(parABSTRACTTYPE);

	// if this atomic concept is concrete...
	if ((iter != params.end()) && (iter->second.nValue == valCONCRETE)) {
		pDummyAtomicConcept->extendProperty(bCONCRETE);
	}

	// push object in a cache aware way
	_pushAtomic<ATOMICCONCEPT>(params, pDummyAtomicConcept);
}


void OWLHANDLER::pushAtomicRole(PARAMETERS& params) {

	// Atomic roles are not pushed into the empty stack
	if ((pOWLParser->mStack.empty()) && (!bPropertyCharacteristicModeOn)) {
		return;
	}

	// set datatype bit is this is indeed a datatype property...
	PARAMETERSITERATOR iter = params.find(parPROPERTYTYPE);
	if ((iter != params.end()) && (iter->second.nValue == valDATAPROPERTY)) {
		pDummyAtomicRole->extendProperty(bCONCRETE);
	}

	// in we are in the special mode, we set the appropriate parameter
	// configure the dummy role
	pDummyAtomicRole->extendProperty(bPropertyCharacteristicModeOn ? mPropertyCharacteristic : 0);

	// push object in a cache aware way
	_pushAtomic<ATOMICROLE>(params, pDummyAtomicRole);

}

void OWLHANDLER::pushInverse(PARAMETERS& params) {
	// Process inverse roles in a special way
	// in the normal case we proceed exactly the same way as with any other element
	if (!bPropertyCharacteristicModeOn) {
		if (pOWLParser->mStack.empty()) return;
		pushOWLSAXElementToStack<INVERSE>(params);
	} else {
		DBG("Skipping inverse tag");
		// if the characteristic is functional or inverseFunctional we have to "flip"
		switch (mPropertyCharacteristic) {
		case bFUNCTIONAL:
			mPropertyCharacteristic = bINVERSEFUNCTIONAL;
			break;
		case bINVERSEFUNCTIONAL:
			mPropertyCharacteristic = bFUNCTIONAL;
			break;
		default:
			break;
		}

		// either way: INVERSE is _not_ pushed to the stack
	}

}


// Prefix handling
void OWLHANDLER::extendPrefixTable(PARAMETERS& params) {
	// get the two parameters
	PARAMETERSITERATOR iter = params.find(parNAME);
	ASSERT(iter != params.end());
	const char* pPrefixName = iter->second.pString;

	iter = params.find(parIRI);
	ASSERT(iter != params.end());
	const char* pUriName = iter->second.pString;

	// copy strings
	INT lPrefix = strlen(pPrefixName);
	char* pPrefixNameCopied = new (pOWLParser->pKnowledgeBase->mPool) char[lPrefix + 1];
	strcpy(pPrefixNameCopied, pPrefixName);

	char* pUriNameCopied = new (pOWLParser->pKnowledgeBase->mPool) char[strlen(pUriName) + 1];
	strcpy(pUriNameCopied, pUriName);

	// extend table with a prefix containing lPrefix many characters
	mPrefixes.insert(STRINGNPAIR(STRINGN(pPrefixNameCopied, lPrefix), pUriNameCopied));

	DBG("\t\tPrefix table extended with: \"%s\" - \"%s\"", pPrefixNameCopied, pUriNameCopied);

	if (strcmp(pPrefixNameCopied, "base") == 0) {
		pBasePrefix = pUriNameCopied;
		DBG("\t\tBase namespace prefix has been saved.");
	}
}


void OWLHANDLER::_insertParameter(PARAMETERS& parameters, PARAMPAIR pair) {

	PARAMETERSRESULTITERATOR iter = parameters.insert(pair);
	if (iter.second == false) {
		// if it has already been there, refresh it
		iter.first->second = pair.second;
	}

}


/// Xerces hook method for processing a new element.
void OWLHANDLER::startElement(const XMLCh* const    uri,
							  const XMLCh* const    localname,
                              const XMLCh* const    qname,
                              const Attributes&     attrs) {

#ifdef DEBUG
	char* pUri= XMLString::transcode(uri);
	char* pQname= XMLString::transcode(qname);
	char* pLocalName= XMLString::transcode(localname);
	DBG("I see start element %s", pLocalName);
	XMLString::release(&pUri);
	XMLString::release(&pLocalName);
	XMLString::release(&pQname);
#endif

	ASSERT(!bLiteralModeOn);

	// Check if we found an element from the OWL namespace, return if not.
	if (!XMLString::equals(uri, XMLOWLURI))
		return;


	// find the callback function associated with localname
	OWLCALLBACK* pHookStructure = obtain_callback(localname);

	// in case of hit let us invoke the function and return
	if (pHookStructure != NULL) {

		// obtain attribute if available and expand the parameter list with it
		if (attrs.getLength() > 0) {
			// get attributes of the XML element
			unsigned int j = 0;
			for (unsigned int i = 0; i < attrs.getLength(); ++i) {
				// transcode attribute
				char* pAttrValue = XMLString::transcode(attrs.getValue(static_cast<XMLSize_t>(i)));
				char* pAttrValueToSave = pAttrValue;
				ASSERT(pAttrValue != NULL);

#ifdef DEBUG
				char* pAttrName = XMLString::transcode(attrs.getLocalName(static_cast<XMLSize_t>(i)));
				DBG("\t\tAttribute \"%s =  %s\".", pAttrName, pAttrValue);
				XMLString::release(&pAttrName);
#endif

				// modify parameters, maybe refactor this later to a better form.
				PARAMKEYS attrName;
				
				if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLIRI)) {
					//
					// TODO: decide if this is an absolute URI
					//
					if (XMLString::startsWith(pAttrValue, "http://")) {
						// if yes, then we add attribute prefix with empty
						_insertParameter(pHookStructure->mParameters, PARAMPAIR(parPREFIX, ""));
					} else {
						// if no, then we add attribute prefix with value of the base prefix
						_insertParameter(pHookStructure->mParameters, PARAMPAIR(parPREFIX, pBasePrefix));
					}

					// IRI is untouched
					attrName = parIRI;

					// Now the full URI is the concatenation of the value of parPrefix and parIRI

				} else if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLAbbreviatedIRI)) {
					//
					// Abbreaviated names
					//
					// parse out the prefix part, i.e. determine the index of the first :
					INT index = XMLString::indexOf(pAttrValue,':');
					ASSERT(index != -1);

					// add attribute prefix with value according to the prefix part
					// but without manifesting the prefix itself as a new string
					PREFIXMAPITERATOR iter = mPrefixes.find(STRINGN(pAttrValue, index));
					ASSERT(iter != mPrefixes.end());
					_insertParameter(pHookStructure->mParameters, PARAMPAIR(parPREFIX, iter->second));

					// change attribute value without creating new string
					pAttrValue = pAttrValue + index + 1;

					DBG("\t\tPrefix part is \"%s\", Non-prefix part is \"%s\"", iter->second, pAttrValue);

					// continue normally
					attrName = parIRI;

					// Now the full URI is the concatenation of the value of parPrefix and parIRI

				} else if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLFacet)) {
					attrName = parFACETDESCRIPTION;
				} else if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLCardinality)) {
					attrName = parCARDINALITY;
				} else if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLName)) {
					attrName = parNAME;
				} else if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLBase)) {
					// insert parameter with value
					_insertParameter(pHookStructure->mParameters, PARAMPAIR(parNAME,"base"));

					attrName = parIRI;
				} else if (XMLString::equals(attrs.getLocalName(static_cast<XMLSize_t>(i)), XMLDataTypeIRI)) {
					//
					// we are dealing with a literal which we consider as a special case of atomic class
					//
					// we set parPREFIX to the (copy of the) datatype URI
					// we set parIRI to the value of the literal
					// TODO: what happens if the datatype URI is not absolute? 
					char* pCopiedDataTypeURI = new (pOWLParser->pKnowledgeBase->mPool) char[strlen(pAttrValue) + 1];
					strcpy(pCopiedDataTypeURI, pAttrValue);
					_insertParameter(pHookStructure->mParameters, PARAMPAIR(parPREFIX, pCopiedDataTypeURI));

					// this is a superspecial case:
					// we return and will arrive to the characters hook
					// there we determine the value, set paramIRI and invoke the hook function
					XMLString::release(&pAttrValue);
					bLiteralModeOn = true;
					pSavedHookStructure = pHookStructure;

					return;
				} else {
					// ignore attribute and process next
					continue;
				}

				// insert parameter with value
				_insertParameter(pHookStructure->mParameters, PARAMPAIR(attrName,pAttrValue));

				// remember strings to release later
				ASSERT((j <= 1));
				pAttrCharsToRelease[j++] = pAttrValueToSave;
			}
		}

		// invoke hook function
		(this->*(pHookStructure->pHookFunction))(pHookStructure->mParameters);

		// release Xerces string(s) if needed
		for (unsigned int i = 0; i < 2; ++i) {
			if (pAttrCharsToRelease[i] != NULL) {
				XMLString::release(&pAttrCharsToRelease[i]);
				pAttrCharsToRelease[i] = NULL;
			}
		}

		// return
		return;
	}

	DBG("\t\tHook is unsuccessful");
	pOWLParser->nrUnknownElements++;

	// that's it, Xerces hook is this easy if we use member function pointers
}

// hook method for processing an end element
// the implementation delegates the bulk of the job to the
// SROIQ constructs themselves
void OWLHANDLER::endElement(const XMLCh* const    uri,
							const XMLCh* const    localname,
                            const XMLCh* const    qname) {

	// check if we found an end element from the OWL namespace
	// discard if not
	if (!XMLString::equals(uri, XMLOWLURI))
		return;


	// check if the stack is empty and return if yes
	if (pOWLParser->mStack.empty())
		return;

#ifdef DEBUG
	char* pTempChar = XMLString::transcode(localname);
	DBG("Closing element: %s, stack size: %d", pTempChar, pOWLParser->mStack.size());
	XMLString::release(&pTempChar);
#endif

	// check if the stack contains only one element:
	// - we have just finalised a top level axiom
	// - we have just finalised an atomic role within a property characteristic axiom
	// - we have just ended a property chain element
	if (pOWLParser->mStack.size() == 1) {
		// check if we just finished a  property chain
		if (XMLString::equals(localname, XMLPropertyChain))
			return;

		// check if we have are inside a property characteristic axiom
		// in this case we basically do nothing as the role is already pushed into the cache
		if (bPropertyCharacteristicModeOn) {
			// checkup
			ASSERT(XMLString::equals(localname, XMLObjectProperty) || XMLString::equals(localname, XMLDataProperty));

			// turn off characteristic mode
			bPropertyCharacteristicModeOn = false;
			mPropertyCharacteristic = 0;
		} else {
			DBG("Closing element is on top level, axiom has been found.");
	
			// get axiom
			AXIOM* pAxiom = static_cast<AXIOM*>(pOWLParser->mStack.top());

			//	insert axiom into the knowledge base
			pAxiom->insert(pOWLParser->pKnowledgeBase);
		}

		// pop axiom/atomic role from stack
		pOWLParser->mStack.pop();

		// return
		return;
	}

	// at this point we are sure that there are at-least two elements on the stack
	// pop expression (atomic class, negated class, role, etc) from the stack
	// this expression is finalised and now is ready to help building another structure
	EXPRESSION* pChild = static_cast<EXPRESSION*>(pOWLParser->mStack.top());
	pOWLParser->mStack.pop();

	// let us peek this parent from the stack
	// this structure will be constructed (maybe only partially) by pChild
	// pParent can be either an EXPRESSION or an AXIOM
   	SROIQTERM* pParent = pOWLParser->mStack.top();

   	// start a double-dispatch process using virtual methods
   	// pParent will be constructed using pCachedChild
   	// this is the same as invoking pParent->construct(pCachedChild), using the construct() method in pParent
   	// that matches pChild dynamic type
   	pChild->dispatchConstructInvocation(pParent);
}

// TODO: this may only return a chunk of data, need to append, etc.
void OWLHANDLER::characters (const XMLCh* const chars, const XMLSize_t length) {
	if (!bLiteralModeOn)
		return;

	// get characters 
	char* pChar = XMLString::transcode(chars);
	DBG("Characters: %s", pChar);

	// insert parameter
	_insertParameter(pSavedHookStructure->mParameters, PARAMPAIR(parIRI,pChar));

	// invoke hook function
	(this->*(pSavedHookStructure->pHookFunction))(pSavedHookStructure->mParameters);

	bLiteralModeOn = false;
	pSavedHookStructure = NULL;

	// release
	XMLString::release(&pChar);
}

void OWLHANDLER::fatalError(const SAXParseException& exception) {
    char* pMessage = XMLString::transcode(exception.getMessage());
    ERR("Fatal Error: %s at line %d", pMessage, exception.getLineNumber());
    XMLString::release(&pMessage);
}

void OWLHANDLER::error(const SAXParseException& exception) {
    char* pMessage = XMLString::transcode(exception.getMessage());
    ERR("Error: %s at line %d", pMessage, exception.getLineNumber());
    XMLString::release(&pMessage);
}

void OWLHANDLER::warning(const SAXParseException& exception) {
    char* pMessage = XMLString::transcode(exception.getMessage());
    DBG("Fatal Error: %s at line %d", pMessage, exception.getLineNumber());
    XMLString::release(&pMessage);
}


// constants built at compile time for efficient comparison during XML parsing
const XMLCh OWLHANDLER::XMLOWLURI[]={
	chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, chLatin_w,
	chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g,
	chForwardSlash, chDigit_2, chDigit_0, chDigit_0, chDigit_2, chForwardSlash, chDigit_0, chDigit_7,
	chForwardSlash, chLatin_o, chLatin_w, chLatin_l, chPound, chNull
};

const XMLCh OWLHANDLER::XMLOWLTHING[]={
	chLatin_T, chLatin_h, chLatin_i, chLatin_n, chLatin_g, chNull
};


const XMLCh OWLHANDLER::XMLOWLNOTHING[]={
	chLatin_N, chLatin_o, chLatin_t, chLatin_h, chLatin_i, chLatin_n, chLatin_g, chNull
};

const XMLCh OWLHANDLER::XMLSubClassOf[]={
	chLatin_S, chLatin_u, chLatin_b, chLatin_C, chLatin_l, chLatin_a, chLatin_s, chLatin_s,
	chLatin_O, chLatin_f, chNull
};


const XMLCh OWLHANDLER::XMLSubObjectPropertyOf[]={
	chLatin_S, chLatin_u, chLatin_b, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLSubDataPropertyOf[]={
	chLatin_S, chLatin_u, chLatin_b, chLatin_D, chLatin_a, chLatin_t, chLatin_a,
	chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t,
	chLatin_y, chLatin_O, chLatin_f, chNull
};


const XMLCh OWLHANDLER::XMLSameIndividual[]={
	chLatin_S, chLatin_a, chLatin_m, chLatin_e, chLatin_I, chLatin_n, chLatin_d,
	chLatin_i, chLatin_v, chLatin_i, chLatin_d, chLatin_u, chLatin_a, chLatin_l,
	chNull
};

const XMLCh OWLHANDLER::XMLDifferentIndividuals[]={
	chLatin_D, chLatin_i, chLatin_f, chLatin_f, chLatin_e, chLatin_r, chLatin_e,
	chLatin_n, chLatin_t, chLatin_I, chLatin_n, chLatin_d, chLatin_i, chLatin_v,
	chLatin_i, chLatin_d, chLatin_u, chLatin_a, chLatin_l, chLatin_s, chNull
};


const XMLCh OWLHANDLER::XMLClassAssertion[]={
	chLatin_C, chLatin_l, chLatin_a, chLatin_s, chLatin_s, chLatin_A, chLatin_s,
	chLatin_s, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_o, chLatin_n,
	chNull
};


const XMLCh OWLHANDLER::XMLObjectPropertyAssertion[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y,
	chLatin_A, chLatin_s, chLatin_s, chLatin_e, chLatin_r, chLatin_t, chLatin_i,
	chLatin_o, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLNegativeObjectPropertyAssertion[]={
	chLatin_N, chLatin_e, chLatin_g, chLatin_a, chLatin_t, chLatin_i, chLatin_v,
	chLatin_e, chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t,
	chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t,
	chLatin_y, chLatin_A, chLatin_s, chLatin_s, chLatin_e, chLatin_r, chLatin_t,
	chLatin_i, chLatin_o, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLDataPropertyAssertion[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_P, chLatin_r, chLatin_o,
	chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chLatin_A, chLatin_s,
	chLatin_s, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_o, chLatin_n,
	chNull
};

const XMLCh OWLHANDLER::XMLNegativeDataPropertyAssertion[]={
	chLatin_N, chLatin_e, chLatin_g, chLatin_a, chLatin_t, chLatin_i, chLatin_v,
	chLatin_e, chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_P, chLatin_r,
	chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chLatin_A,
	chLatin_s, chLatin_s, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_o,
	chLatin_n, chNull
};


const XMLCh OWLHANDLER::XMLEquivalentClasses[]={
	chLatin_E, chLatin_q, chLatin_u, chLatin_i, chLatin_v, chLatin_a, chLatin_l,
	chLatin_e, chLatin_n, chLatin_t, chLatin_C, chLatin_l, chLatin_a, chLatin_s,
	chLatin_s, chLatin_e, chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLEquivalentObjectProperties[]={
	chLatin_E, chLatin_q, chLatin_u, chLatin_i, chLatin_v, chLatin_a, chLatin_l,
	chLatin_e, chLatin_n, chLatin_t, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_i, chLatin_e, chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLEquivalentDataProperties[]={
	chLatin_E, chLatin_q, chLatin_u, chLatin_i, chLatin_v, chLatin_a, chLatin_l,
	chLatin_e, chLatin_n, chLatin_t, chLatin_D, chLatin_a, chLatin_t, chLatin_a,
	chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t,
	chLatin_i, chLatin_e, chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLDisjointObjectProperties[]={
	chLatin_D, chLatin_i, chLatin_s, chLatin_j, chLatin_o, chLatin_i, chLatin_n,
	chLatin_t, chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t,
	chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t,
	chLatin_i, chLatin_e, chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLDisjointUnion[]={
	chLatin_D, chLatin_i, chLatin_s, chLatin_j, chLatin_o, chLatin_i, chLatin_n,
	chLatin_t, chLatin_U, chLatin_n, chLatin_i, chLatin_o, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLDisjointDataProperties[]={
	chLatin_D, chLatin_i, chLatin_s, chLatin_j, chLatin_o, chLatin_i, chLatin_n,
	chLatin_t, chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_P, chLatin_r,
	chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_e,
	chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLDisjointClasses[]={
	chLatin_D, chLatin_i, chLatin_s, chLatin_j, chLatin_o, chLatin_i, chLatin_n,
	chLatin_t, chLatin_C, chLatin_l, chLatin_a, chLatin_s, chLatin_s, chLatin_e,
	chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLObjectComplementOf[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_C,
	chLatin_o, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chLatin_m, chLatin_e,
	chLatin_n, chLatin_t, chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLObjectOneOf[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_O,
	chLatin_n, chLatin_e, chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLDataOneOf[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_O, chLatin_n, chLatin_e,
	chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLDataComplementOf[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_C, chLatin_o, chLatin_m,
	chLatin_p, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t,
	chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLClass[]={
	chLatin_C, chLatin_l, chLatin_a, chLatin_s, chLatin_s, chNull
};

const XMLCh OWLHANDLER::XMLDatatype[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull
};

const XMLCh OWLHANDLER::XMLFacet[]={
	chLatin_f, chLatin_a, chLatin_c, chLatin_e, chLatin_t, chNull
};

const XMLCh OWLHANDLER::XMLFacetRestriction[]={
	chLatin_F, chLatin_a, chLatin_c, chLatin_e, chLatin_t, 
	chLatin_R, chLatin_e, chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t,
	chLatin_i, chLatin_o, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLDatatypeDefinition[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_t, chLatin_y, chLatin_p, chLatin_e, 
	chLatin_D, chLatin_e, chLatin_f, chLatin_i, chLatin_n, chLatin_i, chLatin_t, chLatin_i,
	chLatin_o, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLDatatypeRestriction[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_t, chLatin_y, chLatin_p, chLatin_e, 
	chLatin_R, chLatin_e, chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t,
	chLatin_i, chLatin_o, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLObjectHasValue[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_H,
	chLatin_a, chLatin_s, chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e,
	chNull
};

const XMLCh OWLHANDLER::XMLDataHasValue[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_H, chLatin_a, chLatin_s, 
	chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chNull
};


const XMLCh OWLHANDLER::XMLObjectSomeValuesFrom[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_S,
	chLatin_o, chLatin_m, chLatin_e, chLatin_V, chLatin_a, chLatin_l, chLatin_u,
	chLatin_e, chLatin_s, chLatin_F, chLatin_r, chLatin_o, chLatin_m, chNull
};

const XMLCh OWLHANDLER::XMLObjectAllValuesFrom[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_A,
	chLatin_l, chLatin_l, chLatin_V, chLatin_a, chLatin_l, chLatin_u,
	chLatin_e, chLatin_s, chLatin_F, chLatin_r, chLatin_o, chLatin_m, chNull
};

const XMLCh OWLHANDLER::XMLDataSomeValuesFrom[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_S, chLatin_o, chLatin_m,
	chLatin_e, chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chLatin_s,
	chLatin_F, chLatin_r, chLatin_o, chLatin_m, chNull
};

const XMLCh OWLHANDLER::XMLDataAllValuesFrom[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_A, chLatin_l, chLatin_l,
	chLatin_V, chLatin_a, chLatin_l, chLatin_u,	chLatin_e, chLatin_s, chLatin_F,
	chLatin_r, chLatin_o, chLatin_m, chNull
};

const XMLCh OWLHANDLER::XMLObjectIntersectionOf[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_I,
	chLatin_n, chLatin_t, chLatin_e, chLatin_r, chLatin_s, chLatin_e, chLatin_c,
	chLatin_t, chLatin_i, chLatin_o, chLatin_n, chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLDataIntersectionOf[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_I, chLatin_n, chLatin_t,
	chLatin_e, chLatin_r, chLatin_s, chLatin_e, chLatin_c, chLatin_t, chLatin_i,
	chLatin_o, chLatin_n, chLatin_O, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLObjectHasSelf[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_H,
	chLatin_a, chLatin_s, chLatin_S, chLatin_e, chLatin_l, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLObjectUnionOf[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_U,
	chLatin_n, chLatin_i, chLatin_o, chLatin_n, chLatin_o, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLDataUnionOf[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_U, chLatin_n, chLatin_i,
	chLatin_o, chLatin_n, chLatin_o, chLatin_f, chNull
};

const XMLCh OWLHANDLER::XMLObjectProperty[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLDataProperty[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLInverseObjectProperty[]={
	chLatin_I, chLatin_n, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_e,
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLInverseObjectProperties[]={
	chLatin_I, chLatin_n, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_e,
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_i,
	chLatin_e, chLatin_s, chNull
};


const XMLCh OWLHANDLER::XMLNamedIndividual[]={
	chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_d, chLatin_I, chLatin_n,
	chLatin_d, chLatin_i, chLatin_v, chLatin_i, chLatin_d, chLatin_u, chLatin_a,
	chLatin_l, chNull
};

const XMLCh OWLHANDLER::XMLAnonymousIndividual[]={
	chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_y, chLatin_m, chLatin_o,
	chLatin_u, chLatin_s, chLatin_I, chLatin_n, chLatin_d, chLatin_i, chLatin_v,
	chLatin_i, chLatin_d, chLatin_u, chLatin_a,	chLatin_l, chNull
};

const XMLCh OWLHANDLER::XMLObjectPropertyDomain[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y,
	chLatin_D, chLatin_o, chLatin_m, chLatin_a, chLatin_i, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLObjectPropertyRange[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_P,
	chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y,
	chLatin_R, chLatin_a, chLatin_n, chLatin_g, chLatin_e, chNull
};

const XMLCh OWLHANDLER::XMLDataPropertyDomain[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_P, chLatin_r, chLatin_o,
	chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chLatin_D, chLatin_o,
	chLatin_m, chLatin_a, chLatin_i, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLDataPropertyRange[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_P, chLatin_r, chLatin_o,
	chLatin_p, chLatin_e, chLatin_r, chLatin_t, chLatin_y, chLatin_R, chLatin_a,
	chLatin_n, chLatin_g, chLatin_e, chNull
};

const XMLCh OWLHANDLER::XMLObjectMinCardinality[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_M,
	chLatin_i, chLatin_n, chLatin_C, chLatin_a, chLatin_r, chLatin_d, chLatin_i,
	chLatin_n, chLatin_a, chLatin_l, chLatin_i, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLObjectMaxCardinality[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_M,
	chLatin_a, chLatin_x, chLatin_C, chLatin_a, chLatin_r, chLatin_d, chLatin_i,
	chLatin_n, chLatin_a, chLatin_l, chLatin_i, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLObjectExactCardinality[]={
	chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_E,
	chLatin_x, chLatin_a, chLatin_c, chLatin_t, chLatin_C, chLatin_a, chLatin_r,
	chLatin_d, chLatin_i, chLatin_n, chLatin_a, chLatin_l, chLatin_i, chLatin_t,
	chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLDataMinCardinality[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_M, chLatin_i, chLatin_n,
	chLatin_C, chLatin_a, chLatin_r, chLatin_d, chLatin_i, chLatin_n, chLatin_a,
	chLatin_l, chLatin_i, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLDataMaxCardinality[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_M, chLatin_a, chLatin_x,
	chLatin_C, chLatin_a, chLatin_r, chLatin_d, chLatin_i, chLatin_n, chLatin_a,
	chLatin_l, chLatin_i, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLDataExactCardinality[]={
	chLatin_D, chLatin_a, chLatin_t, chLatin_a, chLatin_E, chLatin_x, chLatin_a,
	chLatin_c, chLatin_t, chLatin_C, chLatin_a, chLatin_r, chLatin_d, chLatin_i,
	chLatin_n, chLatin_a, chLatin_l, chLatin_i, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLFunctionalObjectProperty[]={
	chLatin_F, chLatin_u, chLatin_n, chLatin_c, chLatin_t, chLatin_i, chLatin_o,
	chLatin_n, chLatin_a, chLatin_l, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLFunctionalDataProperty[]={
	chLatin_F, chLatin_u, chLatin_n, chLatin_c, chLatin_t, chLatin_i, chLatin_o,
	chLatin_n, chLatin_a, chLatin_l, chLatin_D, chLatin_a, chLatin_t, chLatin_a,
	chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t,
	chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLInverseFunctionalObjectProperty[]={
	chLatin_I, chLatin_n, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_e,
	chLatin_F, chLatin_u, chLatin_n, chLatin_c, chLatin_t, chLatin_i, chLatin_o,
	chLatin_n, chLatin_a, chLatin_l, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLReflexiveObjectProperty[]={
	chLatin_R, chLatin_e, chLatin_f, chLatin_l, chLatin_e, chLatin_x, chLatin_i,
	chLatin_v, chLatin_e, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLIrreflexiveObjectProperty[]={
	chLatin_I, chLatin_r, chLatin_r, chLatin_e, chLatin_f, chLatin_l, chLatin_e, chLatin_x, chLatin_i,
	chLatin_v, chLatin_e, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLSymmetricObjectProperty[]={
	chLatin_S, chLatin_y, chLatin_m, chLatin_m, chLatin_e, chLatin_t, chLatin_r,
	chLatin_i, chLatin_c, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLAsymmetricObjectProperty[]={
	chLatin_A, chLatin_s, chLatin_y, chLatin_m, chLatin_m, chLatin_e, chLatin_t, chLatin_r,
	chLatin_i, chLatin_c, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLTransitiveObjectProperty[]={
	chLatin_T, chLatin_r, chLatin_a, chLatin_n, chLatin_s, chLatin_i, chLatin_t,
	chLatin_i, chLatin_v, chLatin_e, chLatin_O, chLatin_b, chLatin_j, chLatin_e,
	chLatin_c, chLatin_t, chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e,
	chLatin_r, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLHasKey[]={
	chLatin_H, chLatin_a, chLatin_s, chLatin_K, chLatin_e, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLPropertyChain[]={
	chLatin_P, chLatin_r, chLatin_o, chLatin_p, chLatin_e, chLatin_r, chLatin_t,
	chLatin_y, chLatin_C, chLatin_h, chLatin_a, chLatin_i, chLatin_n, chNull
};

const XMLCh OWLHANDLER::XMLLiteral[]={
	chLatin_L, chLatin_i, chLatin_t, chLatin_e, chLatin_r, chLatin_a, chLatin_l,
	chNull
};

const XMLCh OWLHANDLER::XMLPrefix[]={
	chLatin_P, chLatin_r, chLatin_e, chLatin_f, chLatin_i, chLatin_x, chNull
};

const XMLCh OWLHANDLER::XMLAbbreviatedIRI[]={
	chLatin_a, chLatin_b, chLatin_b, chLatin_r, chLatin_e, chLatin_v, chLatin_i,
	chLatin_a, chLatin_t, chLatin_e, chLatin_d, chLatin_I, chLatin_R, chLatin_I,
	chNull
};

const XMLCh OWLHANDLER::XMLCardinality[]={
	chLatin_c, chLatin_a, chLatin_r, chLatin_d, chLatin_i, chLatin_n, chLatin_a,
	chLatin_l, chLatin_i, chLatin_t, chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLIRI[]={
	chLatin_I, chLatin_R, chLatin_I, chNull
};

const XMLCh OWLHANDLER::XMLName[]={
	chLatin_n, chLatin_a, chLatin_m, chLatin_e, chNull
};

const XMLCh OWLHANDLER::XMLBase[]={
	chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
};

const XMLCh OWLHANDLER::XMLOntology[]={
	chLatin_O, chLatin_n, chLatin_t, chLatin_o, chLatin_l, chLatin_o, chLatin_g,
	chLatin_y, chNull
};

const XMLCh OWLHANDLER::XMLDataTypeIRI[]={
	chLatin_d, chLatin_a, chLatin_t, chLatin_a, chLatin_t, chLatin_y, chLatin_p,
	chLatin_e, chLatin_I, chLatin_R, chLatin_I, chNull
};


const XMLCh OWLHANDLER::XMLImport[]={
	chLatin_I, chLatin_m, chLatin_p, chLatin_o, chLatin_r, chLatin_t, chNull
};

const XMLCh OWLHANDLER::XMLDeclaration[]={
	chLatin_D, chLatin_e, chLatin_c, chLatin_l, chLatin_a, chLatin_r, chLatin_a,
	chLatin_t, chLatin_i, chLatin_o, chLatin_n, chNull
};


